home *** CD-ROM | disk | FTP | other *** search
/ Shareware Grab Bag / Shareware Grab Bag.iso / 090 / ciarnv85.arc / M_DRIVER.ASM < prev    next >
Assembly Source File  |  1986-04-08  |  16KB  |  390 lines

  1.             page   60,132
  2.  
  3. cseg       segment para public 'code'
  4.  
  5. ;****************************************************************************
  6. ;*   Installable device driver for XE12xx modem. This driver handles        *
  7. ;*  low level I/O between the host computer and the modem allowing          *
  8. ;*  the host program to read and write charcters to the device thru the     *
  9. ;*  DOS function calls that are used to read and write to a file.           *
  10. ;*   Take special note that when you wish to send binary data to the modem, *
  11. ;*  for example, when sending voice data, you should directly store data    *
  12. ;*  in the data port rather than writing to the device thru DOS because     *
  13. ;*  the operating system will automatically cancel transmission if a 1Ah    *
  14. ;*  character is detected since that is ordinarily used as the end of file  *
  15. ;*  character. See comments in the first section of the HOST program.       *
  16. ;****************************************************************************
  17. ;
  18. ;           macro ( s )
  19. ;
  20. status     macro  state, err, rc
  21.            ifidn  <state>,<done>
  22.            or     es:word ptr srh_sta_fld[bx],0100h
  23.            endif
  24.            ifidn  <state>,<busy>
  25.            or     es:word ptr srh_sta_fld[bx],0200h
  26.            endif 
  27.            ifidn  <err>,<error>
  28.            or     es:word ptr srh_sta_fld[bx],1000h
  29.            endif
  30.            ifnb   <rc>
  31.            or     es:word ptr srh_sta_fld[bx],rc
  32.            endif
  33.            endm
  34. ;
  35. ;           equates
  36. ;
  37. ; read/write
  38. ;
  39. srh         equ   0              ;static request header start
  40. srh_len     equ   13             ;  "       "      "    length
  41. srh_len_fld equ   srh            ;  "       "      "       "   field
  42. srh_ucd_fld equ   srh+1          ;  "       "      "    unit code field
  43. srh_ccd_fld equ   srh+2          ;  "       "      "    command code field
  44. srh_sta_fld equ   srh+3          ;  "       "      "    status field 
  45. srh_res_fld equ   srh+5          ;  "       "      "    reserved area field 
  46. ;
  47. md          equ   srh+srh_len    ;media descriptor byte 
  48. md_len      equ   1              ;  "       "       "   length
  49. dta         equ   md+md_len      ;disk transfer address
  50. dta_len     equ   4              ;dta length
  51. count       equ   dta+dta_len    ;byte/sector count
  52. count_len   equ   2              ;    "         "   length
  53. ssn         equ  count+count_len ;no meaning on character device
  54. ssn_len     equ   2              ; "    "     "     "       "
  55. ;
  56. inta00      equ   20h       ; 8259 port
  57. inta01      equ   21h       ; 8259 IMR port
  58. eoi         equ   20h
  59. livemask    equ   01000101b
  60. ctlp        equ   2f9h
  61. datap       equ   2f8h
  62. rr          equ   2
  63. xr          equ   1
  64. ;
  65. ;
  66. ; media check 
  67. ;
  68. ret_byte    equ   md+md_len      ;byte returned from driver
  69. ;
  70. ; init 
  71. ;
  72. units       equ   srh+srh_len    ;not set by character devices
  73. units_len   equ   1
  74. br_addr_0   equ  units+units_len ;ending address
  75. br_addr_1   equ   br_addr_0+2
  76. br_addr_len equ   4
  77. ;
  78.  
  79. ;
  80. modem       proc  far
  81. start       equ   $
  82. ;        SPECIAL DEVICE HEADER 
  83. next_dev    dd    -1
  84. attribute   dw    0c000h         ;char device, IOCTL, IBM format
  85. strategy    dw    dev_strategy   ;pointer to device strategy
  86. interrupt   dw    dev_int        ;pointer to device interrupt handler
  87. dev_name    db    'XE1     '     ;name of character device
  88. ;*************************************************************************
  89. ;*   Note the name of the device is XE1. Never name a file by that name. *
  90. ;*   The name of the actual executable file is XE1D.COM.                 *
  91. ;*************************************************************************
  92. ;
  93. rh_off      dw    ?              ;request header offset
  94. rh_seg      dw    ?              ;request header segment
  95. ;
  96. ;        FUNCTION TABLE
  97. ;
  98. funtab      label byte 
  99.             dw    init          ;initialization
  100.             dw    media_check   ;media check ( block only )
  101.             dw    build_bpb     ;build bpb      "     "
  102.             dw    ioctl_in      ;ioctl input
  103.             dw    input         ;input ( read )
  104.             dw    nd_input      ;non_destructive input no wait ( char only )
  105.             dw    in_stat       ;input status                     "    "
  106.             dw    in_flush      ;input flush                      "    "
  107.             dw    output        ;output ( write )
  108.             dw    out_verify    ;output ( write ) with verify
  109.             dw    out_stat      ;output status                    "    "
  110.             dw    out_flush     ;output flush                     "    "
  111.             dw    ioctl_out     ;ioctl output
  112. ;
  113. buff1w      label word          ;label for buff1 set up for word data
  114. buff1       db    128 dup(?)    ;buffer holds 64 character,status byte pairs
  115. b1inptr     dw    0             ;points to next input location in buffer
  116. b1outptr    dw    0
  117. b1count     dw    0
  118. outcount    dw    0
  119. ;****************************************************************************
  120. ;*   The following interrupt routine is the secondary asynchronous          *
  121. ;*  communications interrupt. It is interrupt 0Bh. It is controlled by the  *
  122. ;*  8259 Programmable Interrupt Controller. The IMR is at port 21h. Bit 3   *
  123. ;*  enables the interrupt routine.                                          *
  124. ;*   The interrupt vector to this routine is planted in the device driver   *
  125. ;*  initialization routine. The initialization code is executed once at IPL *
  126. ;*  time and then thrown away. Therefore the initialization routine is the  *
  127. ;*  last module of this program.The interrupt routine accepts any incoming  *
  128. ;*  characters and places them in a circular buffer updating the pointer.   * 
  129. ;****************************************************************************
  130.             assume cs:cseg
  131. intname:
  132.  
  133.             push  ax
  134.             push  dx
  135.             push  di
  136.             push  ds
  137.             mov   ax,cs
  138.             mov   ds,ax         ;set ds
  139.             assume ds:cseg 
  140.             cmp   b1count,40h   ;is buffer full
  141.             jne   intn1         ;if not continue
  142.             cli                 ;cease interrupts
  143.             in    al,inta01     ;8259 port IMR
  144.             or    ax,0008h      ;set bit in IMR
  145.             out   inta01,al     ;disallow 2nd asynch interrupts
  146.             sti                 ;restore interrupts      
  147.             jmp   intend        ;if buffer full don't jam it
  148. intn1:      call  charin        ;get character if any
  149. intend:     mov   al,eoi         ;end of interrupt routine
  150.             out   inta00,al      ;8259 port
  151.             pop   ds
  152.             pop   di
  153.             pop   dx
  154.             pop   ax
  155.             iret
  156. ;
  157. ;
  158. ;                  DEVICE STRATEGY
  159. ;
  160.             assume nothing
  161.             assume cs:cseg
  162. dev_strategy:
  163.  
  164.             mov   rh_seg,es  ;save segment of request header pointer
  165.             mov   rh_off,bx  ;save offset of     "       "      "
  166.             ret
  167. ;
  168. ;                  DEVICE INTERRUPT HANDLER
  169. ;
  170. dev_int:
  171. ;   preserve machine state on entry
  172.             cld             
  173.             push  ds
  174.             push  es
  175.             push  ax
  176.             push  bx
  177.             push  cx
  178.             push  dx
  179.             push  di
  180.             push  si
  181.             push  cs            ;get ready to move cs
  182.             pop   ds            ;move it into ds
  183.             assume ds:cseg 
  184. ;   
  185. ;   do the branch according to the function passed
  186. ;
  187.             
  188.             mov   al,es:[bx]+2  ;get function byte 
  189.             rol   al,1          ;get offset into table
  190.             lea   di,funtab     ;get address of function table
  191.             xor   ah,ah        
  192.             add   di,ax
  193.             jmp   word ptr[di]
  194. ;
  195. ; the following 2 entries are not supported by this device
  196. ;
  197. media_check: jmp  exit
  198. build_bpb:  jmp   exit
  199. ;
  200. ;   ioctl input
  201. ;
  202. ioctl_in:   cmp   b1count,0    
  203.             jz    nochar          ;if no characters in buffer jmp
  204.             mov   di,b1outptr
  205.             mov   bl,buff1+1[di]  ;get status byte of that datum
  206.             and   bl,not livemask 
  207.             mov   dx,ctlp
  208.             in    al,dx           ;get real status byte
  209.             and   al,livemask
  210.             or    al,bl           ;al is resultant byte
  211.             jmp   cont
  212. nochar:     mov   dx,ctlp         ;zero chars in buffer
  213.             in    al,dx           ;real status byte
  214.             and   al,not rr       ;nothing ready
  215. cont:       mov   bx,rh_off    ;restore bx as request header pointer
  216.             les   di,es:dword ptr dta[bx]
  217.                                   ;es:di points to dword adr dta
  218.             mov   es:[di],al      ;return ctl byte 
  219.             mov   es,rh_seg    ;restore es:bx as request header pointer
  220.             mov   es:word ptr count[bx],1  ; number bytes transferred
  221.             status done,noerror,0
  222.             jmp   exit
  223. ;
  224. ;   input
  225. ;
  226. input:      cmp   b1count,0       ;is buffer empty
  227.             jz    input           ;if so loop 
  228.             mov   di,b1outptr     ;index to buff1
  229.             mov   al,buff1[di]    ;get data byte from buff1
  230.             les   di,es:dword ptr dta[bx]
  231.             mov   es:[di],al      ;store data bytes in transfer buffer
  232.             mov   es,rh_seg       ;restore es:bx as request header pointer
  233.             mov   es:word ptr count[bx],1  ;number of bytes transferrred
  234.             dec   b1count         ;one less datum in buff1
  235.             inc   b1outptr
  236.             inc   b1outptr        ;now points to next pair
  237.             and   b1outptr,07Fh   ;if past end of buff1 wrap around
  238.             call  enable          ;if buffer empty reenable interrupt
  239.             jmp   in_stat         ;exit thru in_stat
  240. ;
  241. ;    non_destructive input no wait
  242. ;
  243. nd_input:   cmp   b1count,0        ;chars in buffer ?
  244.             jz    nochar2          ;if not jump
  245.             mov   di,b1outptr      ;index to buff1
  246.             mov   al,buff1[di]     ;get data byte from buff1
  247.             les   di,es:dword ptr dta[bx]
  248.             mov   es:[di],al       ;store data byte in transfer buffer
  249.             mov   es,rh_seg        ;restore es:bx as request header pointer
  250.             mov   es:word ptr count[bx],1   ;number bytes transferred
  251.             jmp   in_stat          ;exit thru in_stat
  252. nochar2:    mov   es:word ptr count[bx],0  ;no bytes transferred
  253.                                    ;exit thru in_stat
  254. ;
  255. ;    input status
  256. ;
  257. in_stat:    cmp   b1count,0
  258.             jz    nochar3
  259.             and   es:word ptr srh_sta_fld[bx],0feffh ;turn off busy bit
  260.             jmp   stat1
  261. nochar3:    status busy,noerror,0  ;set busy bit
  262. stat1:      status done,noerror,0  ;set done bit in status word
  263.             jmp   exit
  264. ;
  265. ;    input flush
  266. ;
  267. in_flush:   mov   b1count,0        ;zero counter of buff1
  268.             mov   b1inptr,0        ; "   pointers "  "
  269.             mov   b1outptr,0
  270.             call  enable           ;reset interrupt
  271.             jmp   exit
  272. ;
  273. ;    output ( write )
  274. ;
  275. output:     mov   cx,es:word ptr count[bx]  ;number of bytes to output
  276.             mov   outcount,0       ;zero the count
  277.             cmp   cx,0             ;make sure you're not about to ...
  278.             jz    out_stat         ;loop 65535 times, if so jump 
  279.             les   di,es:dword ptr dta[bx]
  280.                                    ;make es:di point to dword transfer addr
  281. starto:     mov   dx,ctlp          
  282.             in    al,dx            ;get status
  283.             test  al,xr            ;is transmitter ready ?
  284.             jz    starto           ;if not wait
  285.             mov   al,es:[di]       ;put byte in al
  286.             mov   dx,datap         ;dx is datap
  287.             out   dx,al            ;output byte
  288.             inc   di               ;ready for next byte of transfer buffer
  289.             inc   outcount         ;count bytes
  290.             loop  starto           ;loop until all chars sent
  291.             mov   es,rh_seg        ;restore es:bx as request header pointer
  292.             mov   ax,outcount      ;get count
  293.             mov   es:word ptr count[bx],ax ;return count
  294.             jmp   out_stat         ;exit thru out_stat
  295. ;
  296. ;    output ( write ) with verify
  297. ;
  298. out_verify: jmp   output           ;forget verify for now
  299.             jmp   exit
  300. ;
  301. ;    output status
  302. ;
  303. out_stat:   mov   dx,ctlp
  304.             in    al,dx            ;get status
  305.             test  al,xr            ;is transmitter ready ?
  306.             jz    tbusy            ;if not set busy bit
  307.             and   es:word ptr srh_sta_fld[bx],0feffh ;turn off bust bit
  308.             jmp   stat4
  309. tbusy:      status busy,noerror,0  ;set busy bit
  310. stat4:      status done,noerror,0  ;set done bit            
  311.             jmp   exit
  312. ;
  313. ;    output flush
  314. ;
  315. out_flush:  nop                    ;no output buffer
  316.             jmp   exit
  317. ;
  318. ;    ioctl output
  319. ;
  320. ioctl_out:  mov   cx,es:word ptr count[bx] ;number of bytes to output
  321.             les   di,es:dword ptr dta[bx]  ;es:di points to transfer buffer
  322. startc:     mov   al,es:[di]       ;put byte in al
  323.             mov   dx,ctlp          ;dx is ctlp
  324.             out   dx,al            ;output byte
  325.             inc   di               ;ready for next byte 
  326.             loop  startc           ;loop until all chars sent
  327.             mov   es,rh_seg     ;restore es:bx as request header pointer
  328.             status done,noerror,0  ;set status word
  329.             jmp   exit
  330. ;
  331. ;    re-enable interupts and check for a character already present
  332. ;
  333. enable      proc  near
  334.             cmp   b1count,0        ;chars in buffer ?
  335.             jnz   enex             ;if empty reset PIC
  336.             cli                    ;cease interrupts
  337.             in    al,inta01        ;8259 port IMR
  338.             and   ax,00f7h         ;clear bit in IMR
  339.             out   inta01,al        ;allow 2nd asynch interrupts
  340. ;
  341. ;  charin - check for incoming character and save in buffer
  342. ;
  343. charin:     mov   dx,ctlp       ;ctlp
  344.             in    al,dx         ;read status
  345.             mov   ah,al         ;save it
  346.             test  al,rr         ;check receiver ready
  347.             jz    intend1       ;if not end routine
  348.             mov   dx,datap      ;datap
  349.             in    al,dx         ;read data
  350.             mov   di,b1inptr    ;buff1 input pointer         
  351.             mov   buff1w[di],ax ;store data and status
  352.             inc   di            ;increment index
  353.             inc   di
  354.             mov   b1inptr,di     ;adjust pointer
  355.             and   b1inptr,7Fh    ;if over 127 wrap around
  356.             inc   b1count        ;increment character count
  357. intend1:    sti                    ;restore interrupts
  358. enex:       ret                    ;return
  359. enable      endp
  360. ;
  361. ;    common exit
  362. ;
  363. exit:       pop   si               ;restore all of the registers 
  364.             pop   di
  365.             pop   dx
  366.             pop   cx
  367.             pop   bx
  368.             pop   ax
  369.             pop   es
  370.             pop   ds
  371.             ret
  372. ;
  373. ;   init
  374. ;
  375. init:       mov   es:word ptr br_addr_0[bx],offset init
  376.             mov   es:br_addr_1[bx],cs
  377.             mov   ax,cs         ;set data segment  
  378.             mov   ds,ax
  379.             mov   dx,offset intname 
  380.             mov   ax,250bh      ;function 25 int b
  381.             int   21h           ;plant vector
  382.             call  enable
  383.             status done,noerror,0 ;set status word (done,noerror)
  384.             jmp   exit
  385. ;
  386. modem       endp
  387. cseg        ends
  388.             end
  389.  
  390.